home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
listings
/
v_10_11
/
1011024a
< prev
next >
Wrap
Text File
|
1992-09-07
|
4KB
|
172 lines
/* MSM.c, Copyright (C) 1992 by Jon Shemitz.
A MSM engine and not much else -- this code
has been slashed to minimize magazine space:
Features and *error checking* have been
stripped out and made "exercises for the reader".
*/
#include "msm.h"
// The TaskList is privately declared. Encapsulation
// the "old fashioned" way.
enum OnOff {On, Off};
struct TaskList {
Byte Length;
TaskToken List[NTasks];
TaskList() {Length = 0;}
void Append(TaskToken T) {List[Length++] = T;}
void Delete(TaskToken T);
int ContainsP(TaskToken T)
{return IndexOf(T) < Length;}
private:
int IndexOf(TaskToken T);
// Returns Length iff not found
};
typedef TaskList* PTaskList;
void TaskList::Delete(TaskToken T)
{
int Index = IndexOf(T);
if (Index < Length) Length--;
for ( ; Index < Length; Index++)
List[Index] = List[Index+1];
};
int TaskList::IndexOf(TaskToken T)
{
int Index;
for (Index = 0;
Index < Length && List[Index] != T;
Index++) ;
return Index;
};
struct MSM {
OnOff Tasking;
TaskPtr Ptr[NTasks];
TaskList Foreground;
TaskList Background;
MSM(); // Guarantee initialization
} Taskz;
// Tasks' member functions
Tasks::Tasks(Handler S, Word W, Priorities P)
{
State = S; // Starting state
Waits = W; // Starting waitmap
Priority = P; // Starting priority
TaskToken N; // Find 1st TaskToken
for (N = 0; Taskz.Ptr[N] != 0; N++) ;
Number = N; // Point task to slot
Taskz.Ptr[N] = this; // Point slot to task
if (W == 0) Activate(); // Add to active task list(s)
};
Tasks::~Tasks()
{
if (Waits == 0) Deactivate();
// Remove from active task lists
Taskz.Ptr[Number] = 0;
// Clear the task slot
};
void Tasks::SetPriority(Priorities P)
{
int Moved = ((Priority == 0) != (P == 0)) &&
(Waits == 0);
// Has the task moved from Foreground to Background
// or vice versa?
if (Moved) Deactivate(); // Remove from current list
Priority = P; // Set new priority
if (Moved) Activate(); // Place on new list
};
void Tasks::Activate()
{
PTaskList List = (Priority == 0) ?
& Taskz.Background :
& Taskz.Foreground ;
if (!List->ContainsP(Number)) // If not in list
List->Append(Number); // then add it
};
void Tasks::Deactivate()
{
PTaskList List = (Priority == 0) ?
& Taskz.Background :
& Taskz.Foreground ;
List->Delete(Number); // Delete it iff present
};
// MSM 'engine' code
TaskPtr ThisTask = 0;
MSM::MSM() // Initialize MSM 'engine'
{
for (TaskToken Idx = 0;
Idx < NTasks;
Taskz.Ptr[Idx++] = 0) ;
// Clear all slots
};
void MSM_Run() // Run the 'engine'
{
Taskz.Tasking = On;
while (Taskz.Tasking == On)
if (Taskz.Foreground.Length != 0) {
// Run foreground tasks
Priorities Level;
int Idx, NextLevel;
for (NextLevel = 1, Level = 1;
NextLevel;
Level++) {
NextLevel = 0; // No GetPriority() > Level yet
for (Idx = Taskz.Foreground.Length - 1;
Idx >= 0; Idx--) {
// Execute most-recently-awoken tasks first
ThisTask =
Taskz.Ptr[Taskz.Foreground.List[Idx]];
if (ThisTask->GetPriority() >= Level)
(*ThisTask->GetState())();
// Execute state handler
NextLevel = NextLevel ||
ThisTask->GetPriority() > Level;
// NextLevel == 1 as soon any Priority>Level
};
};
} else {
// Run background tasks
int Idx = Taskz.Background.Length - 1;
while (Idx >= 0) {
ThisTask =
Taskz.Ptr[Taskz.Background.List[Idx--]];
(*ThisTask->GetState())(); // Execute handler
};
};
};
void MSM_Stop() // Handlers can call to stop the engine
{
Taskz.Tasking = Off;
};
TaskPtr Task(TaskToken TT)
{
return Taskz.Ptr[TT];
}
WRAP_EOF